using System;
using System.Collections.Generic;
using System.Linq;

using Atomic.Libraries;
using Atomic.Structures;

namespace Atomic.Thermodynamics.PartitionFunctions
{
	[Serializable]
	public partial class IsobaricPartitionFunction : IGibbsGrandPotential
	{
		private IGibbsGrandPotential inner;

		public IsobaricPartitionFunction(IEnumerable<IIsobaricPartitionFunctionEntry> entries)
		{
			if (entries == null)
			{
				throw new ArgumentNullException();
			}

			Entries = new ReadOnlyList<IIsobaricPartitionFunctionEntry>(entries);

			int atoms = entries.SelectMany(e => e.Composition.Atoms).Distinct().Where(a => a != Atom.Vacancy).Count();

			switch (atoms)
			{
				case 0:
					throw new ArgumentException();

				case 1:
					inner = new UnivariateIsobaricPartitionFunction(entries);
					break;

				case 2:
					inner = new BivariateIsobaricPartitionFunction(entries);
					break;

				default:
					throw new NotSupportedException();
			}
		}

		public double FreeEnergy(double temperature, double pressure, Composition composition)
		{
			return inner.FreeEnergy(temperature, pressure, composition);
		}

		public double Volume(double temperature, double pressure, Composition composition)
		{
			return inner.Volume(temperature, pressure, composition);
		}

		public ChemicalPotential ChemicalPotential(double temperature, double pressure, Composition composition)
		{
			return inner.ChemicalPotential(temperature, pressure, composition);
		}

		public double VolumetricThermalExpansionCoefficient(double temperature, double pressure, Composition composition)
		{
			return inner.VolumetricThermalExpansionCoefficient(temperature, pressure, composition);
		}

		public IHelmholtzGrandPotential HelmholtzPotential
		{
			get
			{
				return inner.HelmholtzPotential;
			}
		}

		public ReadOnlyList<IIsobaricPartitionFunctionEntry> Entries
		{
			get;
			private set;
		}
	}
}
